home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / strategy / xpat2-1.000 / xpat2-1 / xpat2-1.04 / src / rules.c < prev    next >
C/C++ Source or Header  |  1994-09-28  |  10KB  |  361 lines

  1. /*****************************************************************************/
  2. /*                                         */
  3. /*                                         */
  4. /*    X patience version 2 -- module rules.c                     */
  5. /*                                         */
  6. /*    General utility functions for all rule sets                 */
  7. /*    written by Heiko Eissfeldt and Michael Bischoff                 */
  8. /*    see COPYRIGHT.xpat2 for Copyright details                 */
  9. /*                                         */
  10. /*                                         */
  11. /*****************************************************************************/
  12. #include "xpatgame.h"
  13. #include <time.h>
  14.  
  15. Cardindex complete_suit(Pileindex pile, Cardindex i) {
  16.     Rank r;
  17.     Suit s;
  18.     int c;
  19.     if (IS_JOKER(game.cards[i]))
  20.     return 0;
  21.     r = RANK(game.cards[i]);
  22.     s = SUIT(game.cards[i]);
  23.     if (r != Ace)
  24.     return 0;
  25.     for (c = rules.cards_per_color-1; c > 0; --c) {
  26.     if (--i < game.ind[pile] || !game.visible[i])
  27.         return -1;
  28.     if (RANK(game.cards[i]) != ++r || SUIT(game.cards[i]) != s)
  29.         return -1;
  30.     }
  31.     return i;
  32. }
  33.  
  34. /* Move cards to stack. */
  35.  
  36. int stackable(Pileindex pile) {
  37.     if (rules.stackable) {
  38.     return (*rules.stackable)(pile);
  39.     } else {
  40.     Cardindex srcindex;
  41.     srcindex = INDEX_OF_LAST_CARD(pile);
  42.     switch (rules.move_bits & ST_MASK) {
  43.     case ST_NONE:
  44.         return -1;    /* user may not may cards to stack */
  45.     case ST_ONE:
  46.         if (IS_JOKER(game.cards[srcindex]))     /* jokers not movable to stack */
  47.         return -1;
  48.         break;
  49.     case ST_13:
  50.         if ((srcindex = complete_suit(pile, srcindex)) == -1)
  51.         return -1;
  52.         break;
  53.     }
  54.     return srcindex;
  55.     }
  56. }
  57.  
  58. int move_to_stack(Pileindex pile) {    /* pile is slot or tmp */
  59.     Cardindex srcindex;
  60.     Pileindex i;
  61.  
  62.     if (EMPTY(pile))
  63.     return 0;
  64.  
  65.     if ((srcindex = stackable(pile)) == -1)
  66.     return 0;
  67.     for (i = 0; i < rules.numstacks; ++i) {
  68.     if (SUIT(i) != SUIT(game.cards[srcindex]))
  69.         continue;
  70.     if (move_valid(srcindex, i)) {
  71.         store_move(do_move(srcindex, i));
  72.         return 1;
  73.     }
  74.     }
  75.     return 0;
  76. }
  77.  
  78.  
  79. void check_win_game(void) {
  80.     if (game.finished)
  81.     return;        /* don't win twice */
  82.     if (rules.game_won) {
  83.     if (!(*rules.game_won)())
  84.         return;
  85.     } else {
  86.     if (game.ind[FIRST_SLOT] != rules.cards_per_color * rules.numstacks)
  87.         return;
  88.     }
  89.     /* actually, win the game! */
  90.  
  91.     /* all cards on the stacks and not yet notified */
  92.     game.finished = True;
  93.     write_log_file();
  94.     show_message(TXT_YOU_WIN);    /* overwrites OK */
  95.     win_game();        /* hook for additional doodads */
  96.     play_sound("success");
  97. }
  98.  
  99.  
  100.  
  101. int in_relaxed_sequence(int srccard, int dstcard) {
  102.     if (rules.relaxed_valid)
  103.     return (*rules.relaxed_valid)(srccard, dstcard);
  104.     switch (rules.move_bits & US_MASK) {
  105.     case US_RS:
  106.     if (IS_JOKER(dstcard) || IS_JOKER(srccard))
  107.         return 1;
  108.     return RANK(dstcard) == 1 + RANK(srccard) && SUIT(dstcard) == SUIT(srccard);
  109.     case US_R:
  110.     if (IS_JOKER(dstcard) || IS_JOKER(srccard))
  111.         return 1;
  112.     return RANK(dstcard) == 1 + RANK(srccard);
  113.     case US_RA:
  114.     if (IS_JOKER(dstcard) || IS_JOKER(srccard))
  115.         return 1;
  116.     return RANK(dstcard) == 1 + RANK(srccard) && DIFFERENT_COLOR(dstcard, srccard);
  117.     }
  118.     return 0;
  119. }
  120. int in_strong_sequence(int srccard, int dstcard) {
  121.     if (rules.valid)
  122.     return (*rules.valid)(srccard, dstcard);
  123.     switch (rules.move_bits & MG_MASK) {
  124.     case MG_RS:
  125.     if (IS_JOKER(dstcard) || IS_JOKER(srccard))
  126.         return 1;
  127.     return RANK(dstcard) == 1 + RANK(srccard) && SUIT(dstcard) == SUIT(srccard);
  128.     case MG_R:
  129.     if (IS_JOKER(dstcard) || IS_JOKER(srccard))
  130.         return 1;
  131.     return RANK(dstcard) == 1 + RANK(srccard);
  132.     case MG_RA:
  133.     if (IS_JOKER(dstcard) || IS_JOKER(srccard))
  134.         return 1;
  135.     return RANK(dstcard) == 1 + RANK(srccard) && DIFFERENT_COLOR(dstcard, srccard);
  136.     }
  137.     return 0;
  138. }
  139.  
  140. /* find maximum sequence in a nonempty slot for moving */
  141.  
  142. Cardindex slotsequence(Pileindex ind, Cardindex start, Cardindex stop) {
  143.     while (start > game.ind[ind] && game.visible[start-1] && start != stop &&
  144.        in_strong_sequence(game.cards[start], game.cards[start-1]))
  145.     --start;
  146.     return start;
  147. }
  148.  
  149. /* find maximum sequence in a nonempty slot for moving */
  150.  
  151. Cardindex relaxedslotsequence(Pileindex ind, Cardindex start, Cardindex stop) {
  152.     while (start > game.ind[ind] && game.visible[start-1] && start != stop &&
  153.        in_relaxed_sequence(game.cards[start], game.cards[start-1]))
  154.     --start;
  155.     return start;
  156. }
  157.  
  158. int default_movevalid(Cardindex src, Pileindex dstpile) {
  159.     int srcpile, dstcard, srccard;
  160.     srcpile = getpile(src);
  161.     if (srcpile == dstpile)
  162.     return 0;
  163.     switch (game.piletype[srcpile]) {    /* filter out some invalid sources */
  164.     case FacedownDeck:
  165.     return 0;
  166.     case Stack:
  167.     if (!(rules.move_bits & STACK_SOURCE))
  168.         return 0;
  169.     break;
  170.     case FaceupDeck:            /* always valid sources */
  171.     case Tmp:
  172.     case Slot:
  173.     break;
  174.     }
  175.     dstcard = EMPTY(dstpile) ? -1 : game.cards[game.ind[dstpile+1]-1];
  176.     srccard = game.cards[src];
  177.     switch (game.piletype[dstpile]) {
  178.     case Stack:
  179.     if (SUIT(dstpile) != SUIT(game.cards[src]))
  180.         return 0;
  181.     if (rules.stackable) {
  182.         if (src != (*rules.stackable)(srcpile))
  183.         return 0;        /* not possible to move to stack */
  184.     } else {
  185.         switch (rules.move_bits & ST_MASK) {
  186.         case ST_NONE:
  187.         return 0;    /* user may not may cards to stack */
  188.         case ST_ONE:
  189.         if (src != INDEX_OF_LAST_CARD(srcpile) || IS_JOKER(game.cards[src]))
  190.             return 0;
  191.         break;
  192.         case ST_13:
  193.         if (src != complete_suit(srcpile, INDEX_OF_LAST_CARD(srcpile)))
  194.             return 0;
  195.         break;
  196.         }
  197.     }
  198.     /* src is a block of cards without jokers */
  199.     if (RANK(game.cards[INDEX_OF_LAST_CARD(srcpile)]) != (
  200.         dstcard == -1 ? Ace : (1 + RANK(dstcard))         ))
  201.         return 0;
  202.     /* top cards match */
  203.     return 1;
  204.     case Slot:
  205.     if (dstcard == -1) {
  206.         switch (rules.move_bits & ES_MASK) {
  207.         case ES_KINGS:  /* Klondike: only Kings are */
  208.         if (IS_JOKER(game.cards[src]) || RANK(game.cards[src]) == King)
  209.             return 1;
  210.         break;
  211.         case ES_ALL:
  212.         return 1;
  213.         }
  214.     } else {    /* move to non-empty slot */
  215.         return in_relaxed_sequence(srccard, dstcard);
  216.     }
  217.     return 0;    /* fall through: move not allowed */
  218.     case Tmp:
  219.     if (game.ind[srcpile+1] - src != 1)
  220.         return 0;        /* only one card can be moved */
  221.     return dstcard == -1;
  222.     default:
  223.     return 0;
  224.     }
  225. }
  226.  
  227. int debugging = 0;
  228. int move_valid(Cardindex src, Pileindex dstpile) {
  229.  
  230.     if (debugging)
  231.     return 1;
  232.     if (rules.movevalid)
  233.     return (*rules.movevalid)(src, dstpile);
  234.     else
  235.     return default_movevalid(src, dstpile);
  236. }
  237.  
  238.  
  239. Cardindex maxsequence(Pileindex ind, Cardindex cardi) {
  240.     if (!EMPTY(ind)) {    /* the pile may not be empty for this operation */
  241.     switch (game.piletype[ind]) {
  242.     case Stack:
  243.         if (!(rules.move_bits & STACK_SOURCE))
  244.         break;        /* not allowed => break */
  245.         /* fall through: */
  246.     case Tmp:
  247.         return INDEX_OF_LAST_CARD(ind);
  248.     case Slot:
  249.         return slotsequence(ind, INDEX_OF_LAST_CARD(ind), cardi);
  250.     case FaceupDeck:
  251.         if (rules.variant & DECK_SOURCE)
  252.         return INDEX_OF_LAST_CARD(ind);
  253.         break;    /* not allowed => fall through */
  254.     case FacedownDeck:
  255.         if ((rules.variant & DECK_VISIBLE) && !EMPTY(ind))
  256.         return INDEX_OF_LAST_CARD(ind);
  257.         break;
  258.     }
  259.     }
  260.     return -1;        /* this indicates that selection is not possible */
  261. }
  262.  
  263.  
  264.  
  265.  
  266. /* check, if new cards may be dealt */
  267.  
  268. int check_new_cards(void) {
  269.     Pileindex i;
  270.     Cardindex (*testfunc)(Pileindex, Cardindex, Cardindex) = NULL;
  271.  
  272.     if (rules.variant&NODEAL)
  273.     return 0;
  274.     if (rules.new_cards)
  275.     return (*rules.new_cards)();    /* custom function */
  276.  
  277.     if (!CARDS_ON_PILE(IDECK))
  278.     return 0;    /* no more cards */
  279.  
  280.     switch (rules.move_bits & DC_MASK) {
  281.     case DC_ALWAYS:
  282.     return 1;
  283.     /* case DC_NOEMPTY: falls thru */
  284.     case DC_STRONGOK:
  285.     testfunc = slotsequence;
  286.     break;
  287.     case DC_RELAXEDOK:
  288.     testfunc = relaxedslotsequence;
  289.     break;
  290.     }
  291.     for (i = FIRST_SLOT; i <= LAST_SLOT; ++i)
  292.     if (EMPTY(i))
  293.         goto require_check;
  294.     return 1;    /* no empty slot */
  295. require_check:
  296.     if (!testfunc)
  297.     return 0;
  298.     /* may give cards if all nonempty slots are in some sequence */
  299.     for (i = FIRST_SLOT; i <= LAST_SLOT; ++i)
  300.     if (!EMPTY(i))
  301.         if ((*testfunc)(i, INDEX_OF_LAST_CARD(i), INDEX_OF_FIRST_CARD(i))
  302.         != INDEX_OF_FIRST_CARD(i))
  303.         return 0;    /* test failed, pile unsorted */
  304.     return 1;    /* OK, all nonempty pile are in order */
  305. }
  306.  
  307. int std_good_hint(Cardindex srcindex, Pileindex dstpile) {
  308.     Pileindex srcpile = getpile(srcindex);
  309.     int value = 0;
  310.  
  311.     if (IS_STACK(srcpile))      /* don't move from stack if not explicitly requested */
  312.         value = 1;
  313.     else if (IS_STACK(dstpile))    { /* likes to move cards to stack */
  314.     value = (rules.variant & ST_MASK) == ST_13 ? 10000 : 30;
  315.     } else
  316.     value = 15;        /* value of standard move */
  317.  
  318.     /* modifications */
  319.     if (IS_SLOT(dstpile)) {
  320.     switch (rules.move_bits & MG_MASK) {
  321.     case MG_RS:
  322.         if (SUIT(game.cards[srcindex]) == SUIT(game.cards[INDEX_OF_LAST_CARD(dstpile)]))
  323.         value += 15;
  324.         else if (RANK(game.cards[srcindex]) == RANK(game.cards[srcindex-1]) - 1)
  325.         value -= 15;
  326.         else
  327.         value += RANK(game.cards[srcindex]); /* higher ones first */
  328.         break;
  329.     case MG_NONE:
  330.         if (RANK(game.cards[srcindex]) == RANK(game.cards[srcindex-1]) - 1)
  331.         value -= 15;    /* doesn't make anything better */
  332.         else
  333.         value -= 10;
  334.         break;
  335.     }
  336.     }
  337.  
  338.     if (IS_SLOT(srcpile)) {
  339.     if (game.ind[srcpile] == srcindex) {
  340.         /* bonus for creating empty space */
  341.         switch (rules.move_bits & ES_MASK) {
  342.         case ES_NONE:
  343.         value -= 10;    /* no bonus */
  344.         break;
  345.         case ES_KINGS:
  346.         value += 10;
  347.         break;
  348.         case ES_ALL:
  349.         value += 100;
  350.         break;
  351.         }
  352.     } else if (!game.visible[srcindex-1]) {
  353.         /* turn a card */
  354.         value += 10;
  355.     }
  356.     }
  357.     if (value < 1)
  358.     value = 1;
  359.     return value;
  360. }
  361.